package mytest.wd4;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import static mytest.wd4.Test_1.calculateAge;

public class Test_2 {

    private static String searchResultListPath = "$.ConsumerSearchResultResponse.BODY.SEARCHRESULTLIST";

    public static void main(String[] args) {
        String s = "{\n" +
                "    \"ConsumerSearchResultResponse\": {\n" +
                "        \"BODY\": {\n" +
                "            \"SEARCHRESULTLIST\": [\n" +
                "                {\n" +
                "                    \"ADDRESSES\": {\n" +
                "                        \"ADDRESS\": null\n" +
                "                    },\n" +
                "                    \"BUREAUID\": \"1112021005655076\",\n" +
                "                    \"CONFIDENCESCORE\": \"100\",\n" +
                "                    \"DATEOFBIRTH\": \"22-Dec-1982\",\n" +
                "                    \"GENDER\": \"Female\",\n" +
                "                    \"IDENTIFIERS\": {\n" +
                "\n" +
                "                    },\n" +
                "                    \"NAME\": \"OLAMIDE SALIU\",\n" +
                "                    \"PHONENUMBER\": \"08157396945\",\n" +
                "                    \"SURROGATES\": {\n" +
                "\n" +
                "                    }\n" +
                "                },\n" +
                "                {\n" +
                "                    \"ADDRESSES\": {\n" +
                "                        \"ADDRESS\": null\n" +
                "                    },\n" +
                "                    \"BUREAUID\": \"1112022002468249\",\n" +
                "                    \"CONFIDENCESCORE\": \"100\",\n" +
                "                    \"DATEOFBIRTH\": \"23-Nov-1989\",\n" +
                "                    \"GENDER\": \"Female\",\n" +
                "                    \"IDENTIFIERS\": {\n" +
                "\n" +
                "                    },\n" +
                "                    \"NAME\": \"SALIU OLAMIDE\",\n" +
                "                    \"PHONENUMBER\": \"2348157396745\",\n" +
                "                    \"SURROGATES\": {\n" +
                "\n" +
                "                    }\n" +
                "                },\n" +
                "                {\n" +
                "                    \"ADDRESSES\": {\n" +
                "                        \"ADDRESS\": null\n" +
                "                    },\n" +
                "                    \"BUREAUID\": \"1112022005415980\",\n" +
                "                    \"CONFIDENCESCORE\": \"100\",\n" +
                "                    \"DATEOFBIRTH\": \"23-Nov-1989\",\n" +
                "                    \"GENDER\": \"Female\",\n" +
                "                    \"IDENTIFIERS\": {\n" +
                "\n" +
                "                    },\n" +
                "                    \"NAME\": \"OLAMIDE AYINKE SALIU\",\n" +
                "                    \"PHONENUMBER\": \"08157396745\",\n" +
                "                    \"SURROGATES\": {\n" +
                "\n" +
                "                    }\n" +
                "                },\n" +
                "                {\n" +
                "                    \"ADDRESSES\": {\n" +
                "                        \"ADDRESS\": null\n" +
                "                    },\n" +
                "                    \"BUREAUID\": \"1112023000277044\",\n" +
                "                    \"CONFIDENCESCORE\": \"100\",\n" +
                "                    \"DATEOFBIRTH\": \"28-Apr-1995\",\n" +
                "                    \"GENDER\": \"Female\",\n" +
                "                    \"IDENTIFIERS\": {\n" +
                "\n" +
                "                    },\n" +
                "                    \"NAME\": \"KEHINDE MONSURAT APETU\",\n" +
                "                    \"PHONENUMBER\": \"08157396945\",\n" +
                "                    \"SURROGATES\": {\n" +
                "\n" +
                "                    }\n" +
                "                }\n" +
                "            ]\n" +
                "        },\n" +
                "        \"HEADER\": {\n" +
                "            \"RESPONSETYPE\": {\n" +
                "                \"CODE\": \"3\",\n" +
                "                \"DESCRIPTION\": \"Response Search List \"\n" +
                "            }\n" +
                "        },\n" +
                "        \"REFERENCENO\": \"410535030\",\n" +
                "        \"REQUESTID\": \"1\"\n" +
                "    }\n" +
                "}";
        String s2 = "";
        System.out.println(calculateAgeV2(s2));

    }

    public static String catchGender(String extraBody) {
        if (StringUtils.isBlank(extraBody)) {
            return "STR_NEGATIVE_9999979";
        }
        List<Map<String, Object>> searchResultList = jsonToBeanByPath(extraBody, searchResultListPath, List.class);
        if (CollectionUtils.isEmpty(searchResultList)) {
            return "STR_NEGATIVE_9999979";
        }
        List<String> genderList = searchResultList.stream().map(result -> String.valueOf(result.get("GENDER"))).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(genderList)) {
            return "STR_NEGATIVE_9999979";
        }
        Map<String, Long> genderMap = genderList.stream().collect(Collectors.groupingBy(gender -> gender, Collectors.counting()));
        Optional<Map.Entry<String, Long>> resultGender = genderMap.entrySet().stream().max(Map.Entry.comparingByValue());
        return resultGender.map(Map.Entry::getKey).orElse("STR_NEGATIVE_9999979");
    }

    //ngncreditreference_133_crc_age_v2
    public static String calculateAgeV2(String extraBody) {
        if (StringUtils.isBlank(extraBody)) {
            return "STR_NEGATIVE_9999979";
        }
        List<Map<String, Object>> searchResultList = jsonToBeanByPath(extraBody, searchResultListPath, List.class);
        if (CollectionUtils.isEmpty(searchResultList)) {
            return "STR_NEGATIVE_9999979";
        }
        List<String> birthdayList = searchResultList.stream().map(result -> String.valueOf(result.get("DATEOFBIRTH"))).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(birthdayList)) {
            return "STR_NEGATIVE_9999979";
        }
        Map<String, Long> birthdayMap = birthdayList.stream().collect(Collectors.groupingBy(date -> date, Collectors.counting()));
        Optional<Map.Entry<String, Long>> resultBirthday = birthdayMap.entrySet().stream().max(Map.Entry.comparingByValue());
        if (resultBirthday.isPresent()) {
            return calculateAge(resultBirthday.get().getKey());
        }
        return "STR_NEGATIVE_9999979";
    }

    public static <T> T jsonToBeanByPath(String jsonData, String jsonPath, Class<T> clazz) {
        T result = null;
        //若jsonPath不是已$开头的，直接映射jsonPath值
        if (!StringUtils.startsWith(jsonPath, "$")) {
            return (T) jsonPath;
        }
        if (StringUtils.isNotEmpty(jsonData)) {
            String jsonStr = null;
            if (StringUtils.isNotEmpty(jsonPath)) {
                JSONObject jsonRoot = JSON.parseObject(jsonData);
                Object object = JSONPath.eval(jsonRoot, jsonPath);
                if (object instanceof String) {
                    return (T) object;
                } else if (object instanceof BigDecimal) {
                    // Number Type Default Serialize
                    if (clazz.isAssignableFrom(Double.class)) {
                        Double objVal = ((BigDecimal) object).doubleValue();
                        return (T) objVal;
                    } else if (clazz.isAssignableFrom(Float.class)) {
                        Float objVal = ((BigDecimal) object).floatValue();
                        return (T) objVal;
                    } else {
                        return (T) object;
                    }
                } else if (clazz.isAssignableFrom(Integer.class) || clazz.isAssignableFrom(Long.class)
                        || object instanceof Double) {
                    return (T) object;
                } else if (object instanceof JSONArray) {
                    return (T) object;
                } else if (clazz.isAssignableFrom(JSONObject.class)) {
                    return (T) object;
                }
                // 适配实际值对象与泛型不匹配
                if ((object instanceof Integer || object instanceof Long || object instanceof Double)
                        && clazz.isAssignableFrom(BigDecimal.class)) {
                    return (T) (new BigDecimal(object.toString()));
                }
                JSONObject jsonSingle = (JSONObject) object;
                if (jsonSingle != null) {
                    jsonStr = jsonSingle.toJSONString();
                }
            } else {
                jsonStr = jsonData;
            }
            result = JsonMapper.getInstance().fromJson(jsonStr, clazz);
        }
        return result;
    }

}
